#include "XMLHelper.h"
#include "NodeInfo.h"
#include "Globals.h"

XMLHelper::XMLHelper()
{
	mp_xmlContents = (char *) malloc(sizeof(char)* 200000);
}

XMLHelper::~XMLHelper()
{
	delete[] mp_xmlContents;
}

std::string * XMLHelper::_split(std::string rawInput, char regularExpression, int * count)
{
	std::string * result = new std::string[10];
	std::string line;
	int currentLine = 0;
	for (int i = 0; i < rawInput.length(); ++i)
	{
		if (rawInput[i] != regularExpression)
		{
			line.push_back(rawInput[i]);
		}
		else
		{
			result[currentLine] = line;
			line = "";
			currentLine++;
		}
	}
	result[currentLine] = line;
	currentLine++;
	*count = currentLine;
	return result;
}

bool XMLHelper::Load(char path[])
{
	std::string line;
	std::ifstream myfile(path);
	if (myfile.is_open())
	{
		if (std::getline(myfile, line))
		{
			std::strcpy(mp_xmlContents, line.c_str());
		}
		while (std::getline(myfile, line))
		{
			//std::cout << line << std::endl;
			std::strcat(mp_xmlContents,line.c_str());
		}
		myfile.close();
	}
	else
	{
		std::cout << "Unable to open file";
		return false;
	}
	m_document.parse<0>(mp_xmlContents);
	return true;
}

rapidxml::xml_node<> * XMLHelper::_getElement(char elementName[])
{
	std::string XMLPathRaw = elementName;
	int XMLPathCount = 0;
	std::string * XMLPath = _split(XMLPathRaw, '/', &XMLPathCount);
	rapidxml::xml_node<> * node = m_document.first_node();
	if (node) node = node->first_node();
	for (int i = 0; i < XMLPathCount; ++i)
	{
		if (node)
		{
			if (node->name() == XMLPath[i])
			{
				continue;
			}
			else
			{
				bool isASiblingNameOrAttributeValue = false;
				for (rapidxml::xml_node<> * newNode = node; newNode; newNode = newNode->next_sibling())
				{
					if (newNode->name() == XMLPath[i])
					{
						node = newNode;
						isASiblingNameOrAttributeValue = true;
						break;
					}
					else
					{
						for (rapidxml::xml_attribute<> * attr = newNode->first_attribute(); attr; attr = attr->next_attribute())
						{
							if (attr->value() == XMLPath[i])
							{
								node = newNode;
								isASiblingNameOrAttributeValue = true;
								break;
							}
						}
					}
				}
				if (isASiblingNameOrAttributeValue)
				{
					continue;
				}
			}
			bool isNodeAttributeValue = false;
			for (rapidxml::xml_attribute<> * attr = node->first_attribute(); attr; attr = attr->next_attribute())
			{
				if (attr->value() == XMLPath[i])
				{
					isNodeAttributeValue = true;
					break;
				}
			}
			if (isNodeAttributeValue)
			{
				continue;
			}
			bool isAChildName = false;
			for (rapidxml::xml_node<> * newNode = node->first_node(); newNode; newNode = newNode->next_sibling())
			{
				if (newNode->name() == XMLPath[i])
				{
					node = newNode;
					isAChildName = true;
					break;
				}
			}
			if (isAChildName)
			{
				continue;
			}
		}
	}
	if (node)
	{
		delete[] XMLPath;
		return node;
	}
	else
	{
		delete[] XMLPath;
		return 0;
	}
}

NodeInfo XMLHelper::GetElement(char elementName[])
{
	rapidxml::xml_node<> * node = _getElement(elementName);
	NodeInfo nodeInfo(node->name());
	for (rapidxml::xml_attribute<> * attr = node->first_attribute(); attr; attr = attr->next_attribute())
	{
		nodeInfo.AddAttribute(attr->name(), attr->value());
	}
	return nodeInfo;
}
